-- card: 32930 from stack: in.5 -- bmap block id: 42726 -- flags: 0000 -- background id: 3858 -- name: EjectDisk ----- HyperTalk script ----- on hideObjects hide cd btn "Try It!" end hideObjects on showObjects show cd btn "Try It!" end showObjects -- part 4 (button) -- low flags: 00 -- high flags: A002 -- rect: left=82 top=185 right=219 bottom=175 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 8192 -- line height: 16 -- part name: Try it! ----- HyperTalk script ----- on mouseUp -- eject the specified disk global errGlobal put volumePath() into newVolume if newVolume = empty then exit mouseUp EjectDisk newVolume, "noDialog:errGlobal" if errGlobal ≠ empty then answer "Error: “" & errGlobal & "”" put empty into errGlobal end if end mouseUp -- part contents for background part 38 ----- text ----- 13/50 -- part contents for background part 20 ----- text ----- This XCMD will unmount and eject the specified disk. Trying to eject a non-removable disk will return an error message unless the second parameter to the XCMD is the literal string "EjectAll", in which case the XCMD will attempt to eject any disk. If you specify "EjectAll" and attempt to eject the start-up volume (the disk which has the active system folder on it) the volume will be unmounted/ejected and an error message will be returned. It is probably wise to make sure that no files on the disk to be ejected are open before using this XCMD (see the “OpenFiles” XFCN in this stack). Applications may behave unpredictably, and/or files may be corrupted if you remove a volume without first closing all files on it. Although the XCMD returns an error message if a file (other than the Desktop) is open on a drive which has been ejected, by then the damage may have already been done. Calling Syntax: EjectDisk volumeName, <"EjectAll">, <"noDialog:"errorGlobal> VOLUMENAME : the name of the disk to be ejected. -- part contents for background part 42 ----- text ----- { ejectDisk(VolName «,“noDialog:”errorGlobal»)} { XCMD to unmount and eject a disk} {} { brought to you by: Anup Murarka Eric Carlson } { ALINK: SKEPTIC ALINK: cyNic } { CIS: 76004,3356 } {} { We are part of the Support Tools Development Group, } { Apple Computer, Inc. } {} { please DO NOT contact Mac DTS for support of this code! } {} { please DO contact the authors for support of this code! } {} { Send comments, bug reports, requests to any of the above } { E-mail addresses or to:} {} { (one of us) } { Apple Computer, Inc. } { 900 E. Hamilton, Ave. } { Campbell, CA 95008 } { M/S 72-L } {} { Copyright: © 1989, 1990 by Apple Computer, Inc., all rights reserved. } {} { written by Eric Carlson } { AppleLink: cyNic } { modification history } { Date Initials Comments } { ---- ------ ------------------------------------------------------} { 3/1/90 ec first written } { 6/6/90 ec fixed error in reading “EJECTALL” parameter, added } { 5/31/90 ec additional comments to code } {} unit EjectDisk; interface uses HyperXCmd; procedure MAIN (paramPtr: XCmdPtr); implementation procedure reportToUser (paramPtr: XCmdPtr; msgStr: str255); {} { report something back to the user. } { the last parameter (optional) to an external may contain } { "noDialog" or "noDialog:GlobalName". GlobalName is the name } { of a HyperTalk global variable into which error messages will be } { placed. we've decided to use this approach to avoid confusing } { an error message with a valid result being returned from an XFCN. } {} var tempStr: str255; begin {check the last param to see if the user requested that} { we suppress the error dialog } ZeroToPas(paramPtr, paramPtr^.params[paramPtr^.paramCount]^, tempStr); UprString(tempStr, true); if pos('NODIALOG', tempStr) = 0 then { no special error handling specified, throw up a dialog and return the error message } begin SendCardMessage(paramPtr, concat('answer "', msgStr, '"')); paramPtr^.returnValue := PasToZero(paramPtr, msgStr); end else if (pos(':', tempStr) > 0) then { requested global AND noDialog so we fill in the global and return empty } begin tempStr := copy(tempStr, pos(':', tempStr) + 1, length(tempStr)); { get the name of the HC global to fill } SetGlobal(paramPtr, tempStr, PasToZero(paramPtr, msgStr)); { and fill it } paramPtr^.returnValue := PasToZero(paramPtr, '');{ return empty } end else { requested noDialog only so we return the error condition as the result } paramPtr^.returnValue := PasToZero(paramPtr, msgStr); end;{ procedure } function AskedForHelp (paramPtr: XCmdPtr; syntaxMsg: Str255; copyrightMsg: Str255): boolean; {check to see if the user sent a '?' or a '!' as } { the only parameter. if so we will respond with } { the calling syntax or the copyright/version info } { for this external } {} var firstStr: str255; begin askedForHelp := false; if paramPtr^.paramCount = 1 then begin ZeroToPas(paramPtr, paramPtr^.params[1]^, firstStr); { what is the first param? } if firstStr = '?' then begin reportToUser(paramPtr, syntaxMsg); askedForHelp := true end{ asked for help } else if firstStr = '!' then begin reportToUser(paramPtr, copyRightMsg); askedForHelp := true end;{ asked for copyright info } end;{ one parameter passed } end;{ function } function NumberToString (paramPtr: XCmdPtr; num: LONGINT): Str255; { use the toolbox call rather than HC's } var tempStr: str255; begin NumToString(num, tempStr); NumberToString := tempStr; end; procedure ReportVolError (paramPtr: XCmdPtr; errorNum: integer); var errMsg, tempName: str255; begin case errorNum of{ what caused the problem? } bdNamErr: errMsg := 'Bad volume name.'; extFSErr: errMsg := 'External file system.'; ioErr: errMsg := 'I/O Error.'; nsDrvErr: errMsg := 'No such drive.'; nsvErr: errMsg := 'No such volume.'; paramErr: errMsg := 'No default volume.'; otherwise errMsg := concat('unexpected error #', NumberToString(paramPtr, errorNum)); end;{ case } errMsg := concat('Sorry, ', errMsg); reportToUser(paramPtr, errMsg); { return the error message } end;{ function } function validVolumeName (volumeName: str255): str255; { a volume name must have one (and only one) colon in it, as } { the last character } begin if pos(':', volumeName) = 0 then validVolumeName := concat(volumeName, ':') else validVolumeName := copy(volumeName, 1, pos(':', volumeName)); end; function DriveRemovable (aDQEPtr: DrvQElPtr): boolean; var flagsPtr: ^longint; begin {subtract 4 from the DrvQE1Ptr to grab the long there } flagsPtr := pointer(ord4(aDQEPtr) - 4); DriveRemovable := (BAND(BSR(flagsPtr^, 16), $FF) <> 8); end; function DriveNumToQueElement (driveNum: integer): DrvQElPtr; { given a drive number, return a drive que pointer for that drive} { 12:32 PM 3/1/90 ec } var aQueElement: DrvQElPtr; headPtr: QHdrPtr; begin headPtr := GetDrvQHdr;{ grab the drive que header } if headPtr <> nil then begin aQueElement := DrvQElPtr(headPtr^.qHead); while (aQueElement^.dQDrive <> driveNum) and (aQueElement <> nil) do aQueElement := DrvQElPtr(aQueElement^.qLink); DriveNumToQueElement := aQueElement; end else DriveNumToQueElement := nil; end; procedure ejectDisk (paramPtr: XCmdPtr); var volToEject, tempVar: str255; PB: HParamBlockRec; errorCode: OSErr; begin if AskedForHelp(paramPtr, 'EjectDisk diskName, «“EjectAll”», «“noDialog:”errorGlobal»', '© 1990 Apple Computer, Inc. v.1.1, bu Eric Carlson.') then exit(EjectDisk); if paramPtr^.paramCount = 0 then begin ReportToUser(paramPtr, 'Disk name expected.'); exit(EjectDisk); end else ZeroToPas(paramPtr, paramPtr^.Params[1]^, volToEject); volToEject := validVolumeName(volToEject);{ make sure the volume name is correct } { Since volToEject is a full pathname, no other field is needed} zeroBytes(paramPtr, @PB, sizeOf(PB));{ initialize parameter block. } PB.ioNamePtr := @volToEject;{ the name } PB.ioVolIndex := -1;{ use name ONLY } errorCode := PBHGetVInfo(@PB, false); if errorCode <> noErr then{ any errors? } begin reportVolError(paramPtr, errorCode); exit(EjectDisk); end; tempVar := '';{ no value for the var yet } if not (DriveRemovable(DriveNumToQueElement(PB.ioVDrvInfo))) then { this disk is not removable, check to see if user specified that we should do an "eject" anyway } if paramPtr^.paramCount > 1 then begin ZeroToPas(paramPtr, paramPtr^.Params[2]^, tempVar); UprString(tempVar, true);{ upper case for comparison } end; if tempVar <> 'EJECTALL' then{ don't call eject trap unless specifically instructed to } begin ReportToUser(paramPtr, 'Drive is not removable'); exit(EjectDisk) end; errorCode := PBEject(@PB);{ call for the eject } if errorCode <> noErr then{ error? } begin reportVolError(paramPtr, errorCode); exit(ejectDisk); end; errorCode := PBUnmountVol(@PB);{ now call for the unmount } if errorCode <> noErr then{ error? } begin reportVolError(paramPtr, errorCode); exit(ejectDisk); end; end;{ procedure EjectDisk} procedure MAIN (paramPtr: XCmdPtr); begin ejectDisk(paramPtr); end; end.{ unit EjectDisk}